package com.myh.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.myh.common.constant.ProductConstant;
import com.myh.common.to.SpuBoundTo;
import com.myh.common.to.es.Attrs;
import com.myh.common.to.es.SkuEsModel;
import com.myh.common.utils.R;
import com.myh.gulimall.product.dao.SkuImagesDao;
import com.myh.gulimall.product.dao.SkuInfoDao;
import com.myh.gulimall.product.dao.SkuSaleAttrValueDao;
import com.myh.gulimall.product.entity.*;
import com.myh.gulimall.product.feign.CouponFeignService;
import com.myh.gulimall.product.feign.SearchFeignService;
import com.myh.gulimall.product.feign.WareFeignService;
import com.myh.gulimall.product.service.*;
import com.myh.gulimall.product.to.SkuLadderTo;
import com.myh.gulimall.product.to.SkuMemberPriceTo;
import com.myh.gulimall.product.to.SkuReductionTo;
import com.myh.gulimall.product.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.myh.common.utils.PageUtils;
import com.myh.common.utils.Query;

import com.myh.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SpuInfoDao spuInfoDao;

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Autowired
    private SpuImagesService spuImagesService;

    @Autowired
    private ProductAttrValueService productAttrValueService;

    @Autowired
    private SkuInfoService skuInfoService;

    @Autowired
    private SkuInfoDao skuInfoDao;

    @Autowired
    private SkuImagesService skuImagesService;

    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SearchFeignService searchFeignService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private AttrService attrService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();
        //检索字段
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            queryWrapper.and((wrapper) -> {
                wrapper.eq("id", key).or().like("spu_name", key);
            });
        }
        //分类
        String catelogId = (String) params.get("catelogId");
        if (!StringUtils.isEmpty(catelogId) && Integer.parseInt(catelogId) != 0) {
            queryWrapper.eq("catalog_id", catelogId);
        }
        //品牌
        String brandId = (String) params.get("brandId");
        if (!StringUtils.isEmpty(brandId) && Integer.parseInt(brandId) != 0) {
            queryWrapper.eq("brand_id", brandId);
        }
        //状态
        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            queryWrapper.eq("publish_status", status);
        }
        IPage<SpuInfoEntity> iPage = spuInfoDao.selectPage(
                new Query<SpuInfoEntity>().getPage(params),
                queryWrapper
        );
        PageUtils pageUtils = new PageUtils(iPage);
        List<SpuInfoEntity> records = iPage.getRecords();
        if (!Objects.isNull(records)) {
            List<SpuInfoListVo> collect = records.stream().map((spuInfoEntity) -> {
                SpuInfoListVo spuInfoListVo = new SpuInfoListVo();
                BeanUtils.copyProperties(spuInfoEntity, spuInfoListVo);
                spuInfoListVo.setCatalogName(categoryService.findCatelogPathName(spuInfoListVo.getCatalogId()));
                spuInfoListVo.setBrandName(brandService.findBrandNameByBrandId(spuInfoListVo.getBrandId()));
                return spuInfoListVo;
            }).collect(Collectors.toList());
            pageUtils.setList(collect);
        }
        return pageUtils;
    }

    /**
     * //TODO 高级部分再来完善各种异常发生后数据的回滚
     *
     * @param vo
     */
    @Override
    @Transactional
    public void saveSpuInfo(SpuSaveVo vo) {

        //1保存spu基本信息 表: pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        this.saveBaseSpuInfo(vo, spuInfoEntity);

        //2、保存spu的描述图片 表: pms_spu_info_desc
        List<String> decript = vo.getDecript();
        spuInfoDescService.saveSpuInfoDesc(spuInfoEntity.getId(), decript);

        //3、保存spu的图片集 表: pms_spu_images
        List<String> images = vo.getImages();
        spuImagesService.saveImages(spuInfoEntity.getId(), images);

        //4、保存spu的规格参数 表: pms_product_attr_value

        List<BaseAttrVo> baseAttrs = vo.getBaseAttrs();
        productAttrValueService.saveAttrValue(spuInfoEntity.getId(), baseAttrs);

        //5、保存spu的积分信息 数据库：gulimall_sms 表: sms_spu_bounds
        BoundsVo bounds = vo.getBounds();
        SpuBoundTo spuBoundTo = new SpuBoundTo();
        BeanUtils.copyProperties(bounds, spuBoundTo);
        spuBoundTo.setSpuId(spuInfoEntity.getId());
        R r = couponFeignService.saveSpuBounds(spuBoundTo);
        if (r.getCode() != 0) {
            log.error("远程保存spu信息出现异常");
        }

        //6、保存当前spu对应的所有sku信息

        List<SkusVo> skus = vo.getSkus();
        if (skus != null && skus.size() != 0) {
            skus.forEach((skusVo) -> {
//            private String skuName;
//            private BigDecimal price;
//            private String skuTitle;
//            private String skuSubtitle;
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(skusVo, skuInfoEntity);
                skuInfoEntity.setBrandId(vo.getBrandId());
                skuInfoEntity.setCatalogId(vo.getCatalogId());
                skuInfoEntity.setSpuId(spuInfoEntity.getId());
                skuInfoEntity.setSaleCount(0l);
                //设置默认图片
                List<ImageVo> skusVoImages = skusVo.getImages();
                String s = skusVoImages.stream().filter((imageVo) -> {
                    return imageVo.getDefaultImg() == 1;
                }).map((imageVo) -> {
                    return imageVo.getImgUrl();
                }).collect(Collectors.joining());
                skuInfoEntity.setSkuDefaultImg(s);
                //6.1 保存sku的基本信息 表: pms_sku_info
                skuInfoDao.insert(skuInfoEntity);
                Long skuId = skuInfoEntity.getSkuId();
                List<SkuImagesEntity> skuImagesEntities = skusVoImages.stream().filter((imageVo) -> {
                    return !StringUtils.isEmpty(imageVo.getImgUrl());
                }).map((imageVo) -> {
                    SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                    BeanUtils.copyProperties(imageVo, skuImagesEntity);
                    skuImagesEntity.setSkuId(skuId);
                    return skuImagesEntity;
                }).collect(Collectors.toList());
                //6.2 sku的图片信息 表: pms_sku_images
                skuImagesService.saveBatch(skuImagesEntities);
                List<Attr> attrs = skusVo.getAttr();
                List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrs.stream().map((attr) -> {
                    SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                    skuSaleAttrValueEntity.setSkuId(skuId);
                    return skuSaleAttrValueEntity;
                }).collect(Collectors.toList());
                //6.3 sku的销售属性信息 表: pms_sku_sale_attr_value
                skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
                //6.4 sku的优惠 满减等信息 数据库：gulimall_sms 表: sms_sku_ladder 表: sms_sku_full_reduction 表: sms_member_price
                SkuLadderTo skuLadderTo = new SkuLadderTo();
                BeanUtils.copyProperties(skusVo, skuLadderTo);
                skuLadderTo.setSkuId(skuId);
                skuLadderTo.setAddOther(skusVo.getCountStatus());
                if (skuLadderTo.getFullCount() > 0) {
                    R saveLadderR = couponFeignService.saveLadder(skuLadderTo);
                    if (saveLadderR.getCode() != 0) {
                        log.error("远程保存sku_ladder信息出现异常");
                    }
                }

                SkuReductionTo skuReductionTo = new SkuReductionTo();
                BeanUtils.copyProperties(skusVo, skuReductionTo);
                skuReductionTo.setSkuId(skuId);
                skuReductionTo.setAddOther(skusVo.getPriceStatus());
                if (skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
                    R saveReductionR = couponFeignService.saveReduction(skuReductionTo);
                    if (saveReductionR.getCode() != 0) {
                        log.error("远程保存sku_full_reduction信息出现异常");
                    }
                }


                List<MemberPriceVo> memberPriceVos = skusVo.getMemberPrice();
                if (memberPriceVos != null && memberPriceVos.size() != 0) {
                    memberPriceVos.forEach((memberPriceVo) -> {
                        if (memberPriceVo.getPrice().compareTo(new BigDecimal("0")) == 1) {
                            SkuMemberPriceTo skuMemberPriceTo = new SkuMemberPriceTo();
                            skuMemberPriceTo.setSkuId(skuId);
                            skuMemberPriceTo.setMemberLevelId(memberPriceVo.getId());
                            skuMemberPriceTo.setMemberLevelName(memberPriceVo.getName());
                            skuMemberPriceTo.setMemberPrice(memberPriceVo.getPrice());
                            skuMemberPriceTo.setAddOther(1);
                            R saveMemberPriceR = couponFeignService.saveMemberPrice(skuMemberPriceTo);
                            if (saveMemberPriceR.getCode() != 0) {
                                log.error("远程保存sku_member_price信息出现异常");
                            }
                        }
                    });
                }
            });

        }

    }

    @Override
    public void saveBaseSpuInfo(SpuSaveVo vo, SpuInfoEntity spuInfoEntity) {
        BeanUtils.copyProperties(vo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        spuInfoDao.insert(spuInfoEntity);
    }

    /**
     * 商品上架
     *
     * @param spuId
     */
    @Override
    public void up(Long spuId) {
        //1、给to对象进行赋值
        //1.1 查出当前spuId对应的所有sku信息
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.getSkusByspuId(spuId);
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.getListBySpuId(spuId);
        List<Attrs> attrsList = productAttrValueEntities.stream().filter((productAttrValueEntity) -> {
            return attrService.getSearchTypeByAttrId(productAttrValueEntity.getAttrId()) == 1 && productAttrValueEntities != null;
        }).map((productAttrValueEntity) -> {
            Attrs attrs = new Attrs();
            BeanUtils.copyProperties(productAttrValueEntity, attrs);
            return attrs;
        }).collect(Collectors.toList());
        List<Long> skuIds = skuInfoEntities.stream().map(skuInfoEntity -> {
            return skuInfoEntity.getSkuId();
        }).collect(Collectors.toList());
        Map<Long, Boolean> isHasStock = null;
        try {
            R hasStock = wareFeignService.isHasStock(skuIds);
            TypeReference<List<StockVo>> typeReference = new TypeReference<List<StockVo>>() {
            };
            isHasStock = hasStock.getData(typeReference).stream().collect(Collectors.toMap(stockVo -> stockVo.getSkuId(), stockVo -> stockVo.getStock()));
        } catch (Exception e) {
            log.error("远程调用出现异常{}", e);
        }
        Map<Long, Boolean> getStockBySkuId = isHasStock;
        List<SkuEsModel> skuEsModels = skuInfoEntities.stream().map((skuInfoEntity) -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(skuInfoEntity, skuEsModel);
            skuEsModel.setSkuPrice(skuInfoEntity.getPrice());
            skuEsModel.setSkuImg(skuInfoEntity.getSkuDefaultImg());
            BrandEntity brandEntity = brandService.getById(skuEsModel.getBrandId());
            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setBrandImg(brandEntity.getLogo());
            CategoryEntity categoryEntity = categoryService.getById(skuEsModel.getCatalogId());
            skuEsModel.setCatalogName(categoryEntity.getName());
            skuEsModel.setHotScore(0l);
            if (Objects.isNull(getStockBySkuId)){
                skuEsModel.setHasStock(true);
            }else {
                skuEsModel.setHasStock(getStockBySkuId.get(skuEsModel.getSkuId()));
            }
            skuEsModel.setAttrs(attrsList);
            return skuEsModel;
        }).collect(Collectors.toList());
        R r = searchFeignService.productStatusUp(skuEsModels);
        if (r.getCode() == 0){
            SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
            spuInfoEntity.setId(spuId);
            spuInfoEntity.setUpdateTime(new Date());
            spuInfoEntity.setPublishStatus(ProductConstant.StatusEnum.UP_SPU.getCode());
            spuInfoDao.updateById(spuInfoEntity);
        }else {
            // TODO: 2024/2/28 重复调用？接口幂等性 ？重试机制
        }

    }

}